home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / asmwin13.zip / WINDOWS.ASM < prev    next >
Assembly Source File  |  1989-01-27  |  20KB  |  702 lines

  1. ; Assembly language learning project for Thomas Hill
  2. ;
  3. ; Goal: To design and implement a windowing package in assembly language.
  4. ;
  5. ; Version: 1.0  Jan 1989
  6. ;
  7. ; Version: 1.1  01/27/89 - corrected window size problem with InitWindow/
  8. ;                          EraseTopWin on last (original) window.
  9. ;
  10. ; The routines defined here depend upon the routines found in 
  11. ; David Bennett's "VIDEO.ASM" file.
  12. ;
  13.  
  14. IDEAL                   ; use TASM's ideal mode
  15.  
  16. MODEL   SMALL           ; and small model
  17.  
  18. INCLUDE 'VIDEO.INC'     ; global values
  19.  
  20.  
  21. ; define window record structure
  22.  
  23. STRUC WinRec
  24.         Row     DB      1       ; top left window row
  25.         Col     DB      1       ; leftmost column
  26.         Hite    DB      25      ; hieght of window
  27.         Wide    DB      80      ; width of window
  28.         FAtr    DB      Reverse ; frame attribute, if framed
  29.         BAtr    DB      Normal  ; background attribute for fill
  30.         Flags   DB      SaveBit+FrameBit+FillBit
  31.         Title   DB   20 DUP (0) ; title storage
  32.         SavePtr DW      0       ; segment address of saved screen
  33. ENDS
  34.  
  35. TITLEFLD        EQU     07H     ; offset to title in structure
  36. MAXWINDOW       EQU     15      ; maximum number of windows
  37.  
  38. ;--------------
  39. ; Data Area
  40. ;--------------
  41.  
  42. DATASEG
  43.  
  44. WinList WinRec   5      DUP (<>)        ; array of window structures
  45. TopWindow       DB      0               ; current window structure
  46. WinInUse        DB      0               ; windows currently defined
  47.  
  48. ;copy of the 'current' window displayed
  49.  
  50. CurWin  WinRec  <1,1,25,80,Reverse,Normal,07H,?>
  51.  
  52. WRSize  equ     SIZE CurWin             ; size of the window structure
  53.  
  54. CurWinPtr       DW      0               ; pointer into array
  55.  
  56. ;--------------
  57. ; Code Area
  58. ;--------------
  59.  
  60. CODESEG
  61.  
  62. PROC    ClipXY
  63. ;
  64. ; Procedure to check the current row,col against the current window limits.
  65. ; If the input row or column is outside the window, the ZERO flag is set.
  66. ;
  67. ; Input
  68. ;       AH - Row
  69. ;       AL - Col
  70. ;
  71. ; Returns ZERO if outside current window
  72. ;
  73.  
  74.         push    ax
  75.         push    bx
  76.         cmp     ah,[CurWin.Row]
  77.         jl      NoGood                  ; check against upper row
  78.         cmp     al,[CurWin.Col]
  79.         jl      NoGood                  ; and upper left column
  80.         mov     bl,[CurWin.Row]
  81.         add     bl,[CurWin.Hite]
  82.         cmp     ah,bl
  83.         jge     NoGood                  ; check lower row limit
  84.         mov     bl,[CurWin.Col]
  85.         add     bl,[CurWin.Wide]
  86.         cmp     al,bl
  87.         jge     NoGood                  ; and rightmost column
  88.         xor     ax,ax                   ; all ok, reset zero flag
  89.         inc     ax
  90.         pop     bx
  91.         pop     ax
  92.         ret
  93. NoGood: xor     ax,ax                   ; set ZERO and exit
  94.         pop     bx
  95.         pop     ax
  96.         ret       
  97.  
  98. ENDP ClipXY
  99.  
  100.  
  101. PROC GetCurWin
  102. ;
  103. ; This procedure will compute the offset to the specified window record
  104. ; A pointer is returned in the DS:SI pair.  If the requested window is
  105. ; and invalid handle, the CARRY flag is set on return.
  106. ;
  107. ; Input
  108. ;       AL - window number(handle)
  109. ;
  110. ; Output
  111. ;       CY reset - DS:SI altered
  112. ;       CY set   - no changes
  113.  
  114.         push    ax
  115.         push    bx
  116.         cmp     al,MAXWINDOW
  117.         jg      GCW_Bad
  118.         mov     ah,0                    ; make sure AH = 0
  119.         mov     bx,WRSize               ; size of the window structure
  120.         mul     bx
  121.         mov     si,OFFSET WinList
  122.         add     si,ax                   ; SI now points to window record
  123.         mov     [CurWinPtr],si          ; so does this
  124.         pop     bx
  125.         pop     ax
  126.         clc                             ; clear the carry flag
  127.         ret
  128. GCW_Bad:
  129.         pop     bx
  130.         pop     ax
  131.         stc                             ; set the carry
  132.         ret
  133.  
  134. ENDP GetCurWin
  135.  
  136.  
  137. PROC    FrameWindow
  138. ;
  139. ; THis procedure creates a frame around the specified window coordinates
  140. ;
  141. ; Input
  142. ;       AH - Top row
  143. ;       AL - left column
  144. ;       BH - number of rows
  145. ;       BL - number of columns
  146. ;       DH - attribute for frame
  147. ;
  148. ; Output
  149. ;       None
  150. ;
  151.  
  152.         push    cx
  153.         push    dx
  154.         push    ax
  155.         push    bx
  156.         mov     bl,'╒'
  157.         mov     bh,dh
  158.         mov     cx,1
  159.         call    DWriteCH                ; upper left corner
  160.         inc     al
  161.         pop     bx
  162.         push    bx
  163.         dec     bl
  164.         dec     bl                      ; account for left/right edges
  165.         xor     cx,cx
  166.         mov     cl,bl
  167.         mov     bh,dh
  168.         mov     bl,'═'
  169.         call    DWriteCH                ; top edge
  170.         pop     bx
  171.         push    bx
  172.         dec     bl
  173.         dec     bl
  174.         add     al,bl                   ; end of row
  175.         mov     bh,dh
  176.         mov     bl,'╕'
  177.         mov     cx,1
  178.         call    DWriteCH                ; upper right corner
  179.         pop     bx
  180.         pop     ax
  181.         dec     bh
  182.  
  183. FW_Loop:
  184.  
  185.         inc     ah                      ; row counter
  186.         dec     bh                      ; rows to do
  187.         jz      FW_Bottom
  188.         push    ax
  189.         push    bx
  190.         mov     bh,dh
  191.         mov     bl,'│'
  192.         mov     cx,1
  193.         call    DWriteCH                ; left edge
  194.         pop     bx
  195.         push    bx
  196.         add     al,bl
  197.         dec     al
  198.         mov     bh,dh
  199.         mov     bl,'│'
  200.         mov     cx,1
  201.         call    DWriteCH                ; right edge
  202.         pop     bx
  203.         pop     ax
  204.         jmp     FW_Loop
  205.  
  206. FW_Bottom:
  207.  
  208.         push    bx
  209.         mov     bl,'╘'
  210.         mov     bh,dh
  211.         mov     cx,1
  212.         call    DWriteCH                ; lower left corner
  213.         inc     al
  214.         pop     bx
  215.         push    bx
  216.         dec     bl
  217.         dec     bl
  218.         xor     cx,cx   
  219.         mov     cl,bl
  220.         mov     bh,dh
  221.         mov     bl,'═'
  222.         call    DWriteCH                ; bottom edge
  223.         pop     bx
  224.         push    bx
  225.         dec     bl
  226.         dec     bl
  227.         add     al,bl
  228.         mov     bh,dh
  229.         mov     bl,'╛'
  230.         mov     cx,1
  231.         call    DWriteCH                ; lower right corner
  232.         pop     bx
  233.         pop     dx
  234.         pop     cx
  235.         ret
  236.  
  237. ENDP FrameWindow
  238.  
  239.         
  240. GLOBAL  InitWindows:PROC
  241. PROC    InitWindows
  242. ;
  243. ; This procedure initializes the window array and data structures, 
  244. ; The procedure checks the available memory from DOS using the Allocate 
  245. ; Memory Block DOS call.  If no memory is available in that manner, 
  246. ; we return an error.
  247. ; Note that the contents of the screen at the time of initialization is
  248. ; saved into window 0.  A final ERASETOPWIN call will restore the screen
  249. ; contents at the time INITWINDOWS was called.
  250. ;
  251. ; Input
  252. ;       None        
  253. ;
  254. ; OutPut
  255. ;       CARRY is SET if we could not find any un-used memory.
  256. ;       If CARRY is not set, then AL contains the maximum number of
  257. ;       windows that may be defined.
  258.  
  259.         push    si
  260.         push    di
  261.         push    dx
  262.         push    cx
  263.         push    bx
  264.         mov     bx,MAXSIZE SHR 4
  265.         mov     ah,48H          ; allocate memory block
  266.         int     21H
  267.         jc      IW_NoMem        ; no memory available
  268.         
  269. ; if we have enough memory, save the screen at program startup in window 0
  270.  
  271.         push    ax
  272.         mov     ax,0
  273.         call    GetCurWin       ; point to window 0
  274.         pop     ax
  275.         mov     [(WinRec PTR si).SavePtr],ax
  276.         push    es
  277.         mov     es,ax           ; set up to save screen
  278.         xor     di,di
  279.         mov     ah,[(WinRec PTR si).Row]
  280.         mov     al,[(WinRec PTR si).Col]
  281.         mov     bh,[(WinRec PTR si).Hite]
  282.         mov     bl,[(WinRec PTR si).Wide]
  283.         mov     [(WinRec PTR si).Flags],SaveBit
  284.         call    StoreToMem      ; save whole screen to window 0
  285.         pop     es
  286.         pop     bx
  287.         pop     cx
  288.         pop     dx
  289.         pop     di
  290.         pop     si
  291.         mov     al,MAXWINDOW    ; tell how many windows we support
  292.         clc
  293.         ret
  294.  
  295. IW_NoMem:
  296.  
  297.         pop     bx              ; can't get memory
  298.         pop     cx
  299.         pop     dx
  300.         pop     di
  301.         pop     si
  302.         stc
  303.         ret        
  304.  
  305.  
  306. ENDP    InitWindows
  307.  
  308. GLOBAL  MakeWindow:PROC
  309. PROC    MakeWindow
  310. ;
  311. ; This procedure will create a window record for the passed window, but
  312. ; will not display it.  If no more room exists in the window array,
  313. ; the CARRY flag will be set on return.
  314. ; On exit AL will contain the created window's "handle" for further use.
  315. ;
  316. ; Input
  317. ;       AH - Top Row
  318. ;       AL - Left Column
  319. ;       BH - number of rows
  320. ;       BL - number of columns
  321. ;       CL - Various flags:
  322. ;               Bit 0 - (1) - save underlay; (0) do not save
  323. ;               Bit 1 - (1) - Frame the window; (0) do not frame
  324. ;               Bit 2 - (1) - clear the window; (0) do not clear
  325. ;       DH - Frame attribute
  326. ;       DL - Fill attribute
  327. ;       DS:SI - Title for window, null terminated
  328. ;
  329. ; Output
  330. ;       CARRY SET if invalid window, else
  331. ;       AL - window handle
  332. ;       
  333.  
  334.  
  335.         push    di
  336.         push    si
  337.         push    dx
  338.         push    cx
  339.         push    bx
  340.         push    ax
  341.         mov     al,MAXWINDOW
  342.         cmp     [WinInUse],al           ; no more left?
  343.         jge     MW_Full
  344.         mov     al,[TopWindow]
  345.         inc     al                      ; note: window 0 is always defined
  346.         mov     [TopWindow],al
  347.         call    GetCurWin               ; compute offset to next window rec.
  348.         pop     ax
  349.         pop     bx
  350.         pop     cx
  351.         pop     dx
  352.         mov     [(WinRec PTR si).Row],ah
  353.         mov     [(WinRec PTR si).Col],al
  354.         mov     [(WinRec PTR si).Wide],bl
  355.         mov     [(WinRec PTR si).HIte],bh   ; save the data
  356.         mov     [(WinRec PTR si).FAtr],dh
  357.         mov     [(WinRec PTR si).BAtr],dl
  358.         mov     [(WinRec PTR si).Flags],cl
  359.         mov     ax,@data
  360.         mov     es,ax                   ; set up for move
  361.         mov     di,[CurWinPtr]
  362.         mov     ax,TitleFld
  363.         add     di,ax                   ; address of title field in structure
  364.         pop     si                      ; title address
  365. MW_Loop:
  366.         lodsb                           ; get a byte....
  367.         stosb                           ; ... put a byte
  368.         or      al,al
  369.         jnz     MW_Loop                 ; until null is seen (and moved)        
  370.         mov     si,[CurWinPtr]
  371.         mov     di,OFFSET CurWin
  372.         mov     cx,WRSize
  373.         rep     movsb                   ; also make a copy for ease of access
  374.         inc     [WinInUse]
  375.         pop     di                      ; stack is clear
  376.         mov     al,[TopWindow]          ; window handle
  377.         clc                             ; everything worked, clear carry
  378.         ret     
  379. MW_Full:
  380.         stc                             ; full up, set carry
  381.         pop     ax
  382.         pop     bx
  383.         pop     cx
  384.         pop     dx
  385.         pop     si
  386.         pop     di
  387.         ret     
  388.  
  389. ENDP MakeWindow
  390.  
  391.  
  392. GLOBAL  DispWindow:PROC
  393. PROC    DispWindow
  394. ;
  395. ; This procedure will display the selected window.
  396. ;
  397. ; Input
  398. ;       AL - window handle
  399. ;
  400. ; Output
  401. ;       CY set - invalid handle
  402. ;
  403.         cmp     al,MAXWINDOW
  404.         jl      DW_Good
  405.         jmp     DW_Bad
  406.  
  407. DW_Good:
  408.  
  409.         push    di
  410.         push    si
  411.         push    dx
  412.         push    cx                      ; save the world
  413.         push    bx
  414.         push    ax
  415.         push    si
  416.         call    GetCurWin               ; get the offset
  417.         mov     di,OFFSET CurWin
  418.         mov     cx,WRSize
  419.         rep     movsb                   ; make a copy for ease of access
  420.         pop     si                      ; original offset
  421.  
  422. ; check for underlay save
  423.  
  424.         test    [CurWin.Flags],SaveBit
  425.         jz      DW_NoSave
  426.  
  427. ;now save the underlying bytes
  428.  
  429.  
  430.         mov     al,[CurWin.Hite]
  431.         mov     bl,[CurWin.Wide]
  432.         mul     bl                      ; compute memory needed
  433.         mov     cl,3
  434.         shr     ax,cl                   ; make it a paragraph size
  435.         inc     ax                      ; ( plus one for slack)
  436.         mov     bx,ax
  437.         mov     ah,48H
  438.         int     21H                     ; ask for memory
  439.         jnc     DW_SaveScrn
  440.         jmp      DW_Bad                 ; oops, got problems.
  441.  
  442. DW_SaveScrn:
  443.  
  444.         mov     [CurWin.SavePtr],ax     ; save the pointer
  445.         push    es
  446.         mov     es,ax
  447.         mov     ah,[CurWin.Row]
  448.         mov     al,[CurWin.Col]
  449.         mov     bh,[CurWin.Hite]
  450.         mov     bl,[CurWin.Wide]
  451.         xor     di,di
  452.         call    StoreToMem
  453.         pop     es                      ; saved
  454.  
  455. DW_NoSave:
  456.  
  457.         test    [CurWin.Flags],FrameBit ; frame the window?
  458.         jz      DW_NoFrame
  459.         mov     ah,[CurWin.Row]
  460.         mov     al,[CurWin.Col]
  461.         mov     bh,[CurWin.Hite]
  462.         mov     bl,[CurWin.Wide]
  463.         mov     dh,[CurWin.FAtr]
  464.         call    FrameWindow
  465.  
  466. DW_NoFrame:
  467.  
  468.         mov     si,OFFSET CurWin.Title
  469.         xor     cx,cx
  470.  
  471. DW_Loop:
  472.                 
  473.         lodsb                           ; look for end of string
  474.         or      al,al
  475.         jz      DW_Title
  476.         inc     cx
  477.         jmp     DW_Loop
  478.  
  479. DW_Title:
  480.  
  481.         or      cx,cx                   ; anything there?
  482.         jz      DW_Adj                  ; nope
  483.         mov     al,[CurWin.Wide]
  484.         cmp     al,cl
  485.         jl      DW_Adj                  ; title too long
  486.         mov     si,OFFSET CurWin.Title
  487.         mov     ah,[CurWin.Row]
  488.         mov     al,[CurWin.Wide]
  489.         sub     al,cl
  490.         shr     al,1                    ; AL = ((Wide - len(Title)) / 2
  491.         add     al,[CurWin.Col]
  492.         call    DWriteStrNA
  493.  
  494. DW_Adj:
  495.  
  496.         test    [CurWin.Flags],FrameBit
  497.         jz      DW_NoAdj                ; if no frame do not adjust edges
  498.         inc     [CurWin.Row]
  499.         inc     [CurWin.Col]
  500.         dec     [CurWin.Hite]
  501.         dec     [CurWin.Hite]
  502.         dec     [CurWin.Wide]
  503.         dec     [CurWin.Wide]           ; adjust for frame characters
  504.  
  505. DW_NoAdj:
  506.  
  507.         test    [CurWin.Flags],FillBit  ; clear the window?
  508.         jz      DW_Exit
  509.         mov     ah,[CurWin.Row]
  510.         mov     al,[CurWin.Col]
  511.         mov     bh,[CurWin.Hite]
  512.         mov     bl,[CurWin.Wide]
  513.         mov     dh,[CurWin.BAtr]
  514.         mov     dl,' '                  ; default fill is space
  515.         call    DFillCH
  516.  
  517. DW_Exit:
  518.  
  519.         mov     di,[CurWinPtr]
  520.         mov     si,OFFSET CurWin
  521.         mov     cx,WRSize               ; make sure both copies of the
  522.         rep     movsb                   ; window record are the same
  523.         clc
  524.         pop     ax
  525.         pop     bx
  526.         pop     cx
  527.         pop     dx
  528.         pop     si
  529.         pop     di
  530.         ret     
  531.  
  532. DW_Bad:
  533.  
  534.         stc
  535.         ret     
  536.  
  537.  
  538. ENDP DispWindow
  539.  
  540. GLOBAL  EraseTopWin:PROC
  541. PROC    EraseTopWin
  542. ;
  543. ; THis procedure will erase the current, or top window.  If the background
  544. ; was saved, it is put back.  The  Current Window will be set to the
  545. ; window immediately 'below' the top window.
  546. ;
  547. ; Input
  548. ;       None
  549. ;
  550. ; Output
  551. ;       CY - set if window stack underflow (no window to erase)
  552. ;
  553.         push    di
  554.         push    si
  555.         push    dx
  556.         push    cx
  557.         push    bx
  558.         push    ax
  559.         mov     ah,[CurWin.Row]
  560.         mov     al,[CurWin.Col]
  561.         mov     bh,[CurWin.Hite]
  562.         mov     bl,[CurWin.Wide]
  563.         test    [CurWin.Flags],FrameBit
  564.         jz      ETW_NoAdj                       ; no frame do not adjust
  565.         dec     ah
  566.         dec     al                              ; adjust for frame
  567.         inc     bl
  568.         inc     bl
  569.         inc     bh
  570.         inc     bh
  571.  
  572. ETW_NoAdj:
  573.  
  574.         push    ds
  575.         mov     dx,[CurWin.SavePtr]             ; segment of image
  576.         xor     si,si
  577.         call    StoreToScr                      ; put the underlay back
  578.         pop     ds
  579.         mov     al,[TopWindow]
  580.         dec     al
  581.         mov     [TopWindow],al
  582.         call    GetCurWin                       ; update pointer into array
  583.         mov     di,OFFSET CurWin
  584.         mov     cx,WRSize
  585.         rep     movsb                           ; update copy of structure
  586.         clc                                     ; everything ok.
  587.  
  588. ETW_Exit:
  589.  
  590.         pop     ax
  591.         pop     bx
  592.         pop     cx
  593.         pop     dx
  594.         pop     si
  595.         pop     di
  596.         ret
  597.  
  598. ETW_Bad:
  599.  
  600.         stc
  601.         jmp     ETW_Exit
  602.  
  603. ENDP EraseTopWin
  604.  
  605.  
  606. GLOBAL  WWriteStr:PROC
  607. PROC    WWriteStr
  608. ;
  609. ; This proceudre will attempt to write the passed null terminated string
  610. ; in the current window.  If the starting row,col is not within the window,
  611. ; nothing is written.  If the string is too long to fit the current window,
  612. ; the string is wrapped at the window edge.  If the string wraps past the
  613. ; bottom of the window, the window is scrolled up.
  614. ;
  615. ; Input
  616. ;       AH - Row 
  617. ;       AL - Col 
  618. ;       BH - Attribute
  619. ;       DS:SI - string pointer
  620. ;
  621. ; Output
  622. ;       CARRY SET if string truncated or not written.
  623. ;       DS:SI points to byte following null, or character which truncated.
  624.  
  625.         push    di
  626.         push    dx
  627.         push    cx
  628.         push    bx
  629.         call    ClipXY          ; check starting point
  630.         jz      WWS_Bad         ; cannot write
  631.  
  632. WWS_Loop:
  633.  
  634.         push    ax
  635.         lodsb                   ; character
  636.         or      al,al           ; null ?
  637.         jz      WWS_Exit        ; yes, done.
  638.         mov     bl,al           ; character to bl
  639.         pop     ax
  640.         mov     cx,1
  641.         call    DWriteCH        ; write it
  642.         inc     al              ; next column
  643.         call    ClipXY          ; gone too far?
  644.         jnz     WWS_Loop        ; next char
  645.         inc     ah              ; next row if at edge
  646.         mov     al,[CurWin.Col] ; start at left edge
  647.         call    ClipXY          ; check new row value
  648.         jnz     WWS_Loop        ; no problem
  649.         dec     ah              ; back row up one
  650.         push    ax
  651.         push    bx
  652.         push    cx
  653.         push    dx
  654.         mov     ah,06H          ; ROM VIDEO BIOS service
  655.         mov     al,01           ; scroll one line
  656.         mov     ch,[CurWin.Row]
  657.         mov     cl,[CurWin.Col]
  658.         dec     cl
  659.         dec     ch              ; make zero based for BIOS
  660.         mov     dx,cx
  661.         add     dh,[CurWin.Hite]
  662.         add     dl,[CurWin.Wide]
  663.         test    [CurWin.Flags],FrameBit
  664.         jz      WWS_NoAdj
  665.         dec     dh
  666.         dec     dl              ; adjust for frame
  667.  
  668. WWS_NoAdj:
  669.  
  670.         mov     bh,[CurWin.BAtr]
  671.         int     10H             ; all set up, scroll the window
  672.         pop     ax
  673.         pop     bx
  674.         pop     cx
  675.         pop     dx
  676.         jmp     WWS_Loop        ; and keep going
  677.  
  678. WWS_Bad:
  679.         pop     bx
  680.         pop     cx              ; done all we can.
  681.         pop     dx
  682.         pop     di
  683.         stc
  684.         ret
  685.  
  686. WWS_Exit:
  687.  
  688.         pop     ax
  689.         pop     bx              ; normal exit
  690.         pop     cx
  691.         pop     dx
  692.         pop     di
  693.         clc
  694.         ret
  695.  
  696. ENDP WWriteStr
  697.         
  698.  
  699. END
  700.  
  701.  
  702.